home *** CD-ROM | disk | FTP | other *** search
- /*
- * convsqrs.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* CONVSQRS: function performs converging squares algorithm,
- * which finds a peak by iteratively choosing highest
- * density peak from low to higher resolutions
- */
-
- #define LT_GT > /* greater than finds upward peaks for PEAKUP */
- #define ELEMENT(P,N,I,J) (( (int) (*(P + I * N + J))) & 0x0ff)
- /* returns int from byte array at address P, coord.s I,J
- * from an array of length N */
- /* macro finds sum of elements in row of image */
- #define SUMROW(IMAGE,WIDTH,ROW,SCOL,ECOL,SUM) \
- SUM = 0; \
- pImage = IMAGE + (ROW) * WIDTH + SCOL; \
- for (col = SCOL; col <= ECOL; col++, pImage++) { \
- SUM += ((long) *pImage) & 0x0ff; \
- }
-
- /* macro finds sum of elements in column of image */
- #define SUMCOL(IMAGE,WIDTH,COL,SROW,EROW,SUM) \
- SUM = 0; \
- pImage = IMAGE + (SROW) * WIDTH + COL; \
- for (row = SROW; row <= EROW; row++, pImage += WIDTH){ \
- SUM += ((long) *pImage) &0x0ff; \
- }
-
- /* macro finds subsquare of peak sum. the order of testing of subsquares
- * is revolved so as to find centroid of equi-intensity plateau */
- #define PEAKSQR(SQRSUM,POSITION,PEAK,I,TEMP) \
- TEMP = I[0]; \
- I[0] = I[1]; \
- I[1] = I[2]; \
- I[2] = I[3]; \
- I[3] = TEMP; \
- PEAK = SQRSUM[I[0]]; \
- POSITION = I[0]; \
- if (SQRSUM[I[1]] LT_GT PEAK){ \
- PEAK = SQRSUM[I[1]]; \
- POSITION = I[1]; \
- }\
- if (SQRSUM[I[2]] LT_GT PEAK){ \
- PEAK = SQRSUM[I[2]]; \
- POSITION = I[2]; \
- } \
- if (SQRSUM[I[3]] LT_GT PEAK){ \
- PEAK = SQRSUM[I[3]]; \
- POSITION = I[3]; \
- }
-
- long
- convsqrs (image, width, height, rowInitial, colInitial, nInitial,
- nFinal, rowPeak, colPeak)
- unsigned char *image; /* pointer to image array */
- long width, height; /* image sidelengths */
- int rowInitial; /* initial start row and column of conv. sqrs wrt image */
- int colInitial;
- int nInitial; /* initial size of converging squares */
- int nFinal; /* sidelength of final converging square */
- int *rowPeak; /* row coord. of peak within final square */
- int *colPeak; /* col coord. of peak within final square */
- {
- unsigned char *pImage; /* pointer to image array */
- long sqrSum[4]; /* sum of elements of squares 1-4 */
- long col1Sum; /* sum of left k-2 length col.s of square */
- long col2Sum; /* sum of right ... */
- long row1Sum, row2Sum; /* sum of top, bottom ... */
- long peak; /* peak value in final square */
- long value; /* long value from byte array */
- int position; /* no. (0-3) of max. square */
- int nSquare; /* incrementor = current sidelength reduced square */
- int sqrIndex[4]; /* revolving indices of 4 subsquares */
- int temp;
- register int sRow, eRow; /* start and end rows cols of output reduced sqr */
- register int sCol, eCol;
- register int row, col; /* row and column incrementors */
-
- /* initialize */
- if (nFinal < 2)
- nFinal = 2; /* square size of reduced array */
- sRow = rowInitial;
- sCol = colInitial;
- if ((sRow + nInitial) >= height) {
- nInitial = height - 1 - sRow;
- }
- if ((sCol + nInitial) >= width) {
- nInitial = width - 1 - sCol;
- }
- eRow = sRow + nInitial;
- eCol = sCol + nInitial;
-
- /* initialize revolving square indices */
- sqrIndex[0] = 0;
- sqrIndex[1] = 1;
- sqrIndex[2] = 2;
- sqrIndex[3] = 3;
-
- /* reduce initial (nImage x nImage square to (nImage-1)x(nImage-1) square */
-
- /* find sums of start and end columns and rows */
- SUMCOL (image, width, sCol, sRow + 1, eRow - 1, col1Sum);
- SUMCOL (image, width, eCol, sRow + 1, eRow - 1, col2Sum);
- SUMROW (image, width, sRow, sCol + 1, eCol - 1, row1Sum);
- SUMROW (image, width, eRow, sCol + 1, eCol - 1, row2Sum);
-
- /* find sums of the 4 (nImage -1)x(nImage-1) squares, and peak square */
- sqrSum[0] = col1Sum + row1Sum + ELEMENT (image, width, sRow, sCol);
- sqrSum[1] = row1Sum + col2Sum + ELEMENT (image, width, sRow, eCol);
- sqrSum[2] = col1Sum + row2Sum + ELEMENT (image, width, eRow, sCol);
- sqrSum[3] = row2Sum + col2Sum + ELEMENT (image, width, eRow, eCol);
-
- PEAKSQR (sqrSum, position, peak, sqrIndex, temp);
-
- /* reduce from (nImage-1)x(nImage-1) square to (nFinal x nFinal) square
- * sequentially, for squares of peak density */
-
- for (nSquare = nInitial - 1; nSquare > nFinal; nSquare--) {
- /* calculate end row and column sums for peak square */
- switch (position) {
- case 0: /* top left square */
- eRow -= 1;
- eCol -= 1;
- col1Sum = col1Sum - ELEMENT (image, width, eRow, sCol);
- SUMCOL (image, width, eCol, sRow + 1, eRow - 1, col2Sum);
- row1Sum = row1Sum - ELEMENT (image, width, sRow, eCol);
- SUMROW (image, width, eRow, sCol + 1, eCol - 1, row2Sum);
- break;
- case 1: /* top right square */
- sCol += 1;
- eRow -= 1;
- SUMCOL (image, width, sCol, sRow + 1, eRow - 1, col1Sum);
- col2Sum = col2Sum - ELEMENT (image, width, eRow, eCol);
- row1Sum = row1Sum - ELEMENT (image, width, sRow, sCol);
- SUMROW (image, width, eRow, sCol + 1, eCol - 1, row2Sum);
- break;
- case 2: /* bottom left square */
- sRow += 1;
- eCol -= 1;
- col1Sum = col1Sum - ELEMENT (image, width, sRow, sCol);
- SUMCOL (image, width, eCol, sRow + 1, eRow - 1, col2Sum);
- SUMROW (image, width, sRow, sCol + 1, eCol - 1, row1Sum);
- row2Sum = row2Sum - ELEMENT (image, width, eRow, eCol);
- break;
- case 3: /* bottom right square */
- sRow += 1;
- sCol += 1;
- SUMCOL (image, width, sCol, sRow + 1, eRow - 1, col1Sum);
- col2Sum = col2Sum - ELEMENT (image, width, sRow, eCol);
- SUMROW (image, width, sRow, sCol + 1, eCol - 1, row1Sum);
- row2Sum = row2Sum - ELEMENT (image, width, eRow, sCol);
- break;
- }
-
- /* find sums of 4 (nSquare-1)x(nSquare-1) squares and peak square */
- sqrSum[0] = col1Sum + row1Sum + ELEMENT (image, width, sRow, sCol);
- sqrSum[1] = row1Sum + col2Sum + ELEMENT (image, width, sRow, eCol);
- sqrSum[2] = col2Sum + row2Sum + ELEMENT (image, width, eRow, sCol);
- sqrSum[3] = row2Sum + col2Sum + ELEMENT (image, width, eRow, eCol);
-
- PEAKSQR (sqrSum, position, peak, sqrIndex, temp);
- }
-
- /* find coordinates of (nFinal x nFinal) square */
- switch (position) {
- case 0: /* top left square */
- eRow -= 1;
- eCol -= 1;
- break;
- case 1: /* top right square */
- sCol += 1;
- eRow -= 1;
- break;
- case 2: /* bottom left square */
- sRow += 1;
- eCol -= 1;
- break;
- case 3: /* bottom right square */
- sRow += 1;
- sCol += 1;
- break;
- }
-
- /* find peak element and its position within final square */
- peak = ELEMENT (image, width, sRow, sCol);
- *rowPeak = sRow;
- *colPeak = sCol;
-
- for (row = sRow; row <= eRow; row++) {
- for (col = sCol; col <= eCol; col++) {
- if ((value = ELEMENT (image, width, row, col)) LT_GT peak) {
- peak = value;
- *rowPeak = row;
- *colPeak = col;
- }
- }
- }
-
- return (peak);
- }
-